#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#define SOCKET_PATH "/tmp/unix_socket_example" // 与服务端路径一致

void send_fd(int socket, int fd_to_send)
{
    char dummy = 'X';

    // 1. 初始化控制缓冲区
    char ctrl_buf[CMSG_SPACE(sizeof(int))];
    struct msghdr msg = {0};

    // 2. 设置常规数据载体
    struct iovec io = {
        .iov_base = &dummy,
        .iov_len = 1 // 至少1字节
    };
    msg.msg_iov = &io;
    msg.msg_iovlen = 1;

    // 3. 绑定控制缓冲区
    msg.msg_control = ctrl_buf;
    msg.msg_controllen = CMSG_SPACE(sizeof(int)); // 关键！

    // 4. 填充控制消息
    struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
    if (!cmsg)
    {
        perror("CMSG_FIRSTHDR failed");
        exit(1);
    }
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
    memcpy(CMSG_DATA(cmsg), &fd_to_send, sizeof(int)); // 安全复制

    // 5. 发送并校验
    if (sendmsg(socket, &msg, 0) < 0)
    {
        perror("sendmsg failed");
    }else{
      printf("send success\n");
    }
}

int main()
{
    int sock_fd;
    struct sockaddr_un server_addr;
    const char *message = "Hello from AF_UNIX client!";

    // 1. 创建套接字
    sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sock_fd == -1)
    {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    // 2. 连接服务端
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sun_family = AF_UNIX;
    strncpy(server_addr.sun_path, SOCKET_PATH, sizeof(server_addr.sun_path) - 1);

    if (connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
    {
        perror("connect");
        close(sock_fd);
        exit(EXIT_FAILURE);
    }
    int file_fd = open("/home/bzsg/workspace/study/linuxc/assets/des.txt", O_RDONLY); // 示例文件
    // 3. 发送数据
    send_fd(sock_fd, file_fd);
    printf("Message sent: %d\n", file_fd);

    // 4. 关闭连接
    close(sock_fd);
    return 0;
}
